<?php
/**
 * Here is your custom functions.
 */

use DfaFilter\SensitiveHelper;
use util\RedisTool;

if (!function_exists('httpGet')) {
    /**
     * @param $url
     * @return mixed|string
     */
    function httpGet($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);//设置需要抓取的url
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//设置curl参数，1表示true，让curl_exec执行结果转为字符串，而不是直接输出
        $headerArray = array("Connection: Keep-Alive", "charset=utf-8", "Accept-Language:zh-CN", "Cache-Control: no-cache");
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);//设置http头字段数组属性，
        //如果是https协议请求，需设置ssl验证为false，不验证证书和hosts
        if (substr($url, 0, 5) == "https") {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }
        $timeout = 30;
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);//设置连接等待时间,单位秒
        curl_setopt($ch, CURLOPT_HTTPGET, true);//默认是 GET。
        //执行获取结果
        try {
            $output = curl_exec($ch);//运行curl，请求地址
            //释放curl
            curl_close($ch);
            //解析数据
            return json_decode($output, true);
        } catch (\Exception $ex) {
            return $ex->getMessage();
        }
    }
}

if (!function_exists('httpPost')) {
    /**
     * @param string $url 请求路径
     * @param string $parameters 请求参数
     * @return array|mixed|string
     */
    function httpPost($url, $parameters)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);//设置需要抓取的url
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//设置curl参数，1表示true，让curl_exec执行结果转为字符串，而不是直接输出
        $headerArray = array("Connection: Keep-Alive", "charset=utf-8", "Accept-Language:zh-CN", "Cache-Control: no-cache");
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);//设置http头字段数组属性，
        //如果是https协议请求，需设置ssl验证为false，不验证证书和hosts
        if (substr($url, 0, 5) == "https") {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }
        $timeout = 30;
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);//设置连接等待时间,单位秒
        curl_setopt($ch, CURLOPT_POST, true);//设置为post，
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);//全部数据使用 "POST" 操作来发送。
        //执行获取结果
        try {
            $output = curl_exec($ch);//运行curl，请求地址
            //释放curl
            curl_close($ch);
            //解析数据
            return json_decode($output, true);
        } catch (\Exception $ex) {
            return $ex->getMessage();
        }
    }
}

if (!function_exists('httpCurl')) {
    /**
     * curl请求
     * @param $method
     * @param $url
     * @param array $options
     * @return bool|string
     */
    function httpCurl($method, $url, $options = [])
    {
        $curl = curl_init();
        // GET 参数设置
        if (!empty($options['query'])) {
            $url .= (stripos($url, '?') !== false ? '&' : '?') . http_build_query($options['query']);
        }
        // CURL 头信息设置
        if (!empty($options['headers'])) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $options['headers']);
        }
        // Cookie 信息设置
        if (!empty($options['cookie'])) {
            curl_setopt($curl, CURLOPT_COOKIE, $options['cookie']);
        }
        // POST 数据设置
        if (strtolower($method) === 'post') {
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $options['data']);
        }
        // 请求超时设置
        if (isset($options['timeout']) && is_numeric($options['timeout'])) {
            curl_setopt($curl, CURLOPT_TIMEOUT, $options['timeout']);
        } else {
            curl_setopt($curl, CURLOPT_TIMEOUT, 60);
        }
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        $content = curl_exec($curl);
        curl_close($curl);
        return $content;
    }
}

if (!function_exists('isUrl')) {
    //是否
    function isUrl($url)
    {
        if (preg_match("/^http(s)?:\\/\\/.+/", $url)) return $url;
        return false;
    }
}

if (!function_exists('getDistance')) {
    /**
     * 计算两地距离
     * @param $lng1 string 坐标1
     * @param $lat1 string 坐标1
     * @param $lng2 string 坐标2
     * @param $lat2 string 坐标2
     * @return string
     */
    function getDistance($lng1, $lat1, $lng2, $lat2)//根据经纬度计算距离
    {
        $radLat1 = deg2rad($lat1);
        $radLat2 = deg2rad($lat2);
        $radLng1 = deg2rad($lng1);
        $radLng2 = deg2rad($lng2);
        $a = $radLat1 - $radLat2;//两纬度之差,纬度<90
        $b = $radLng1 - $radLng2;//两经度之差纬度<180
        $distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
        $distance = round($distance); //取整
        if ($distance > 1000) {
            $juli = round($distance / 1000) . 'km';
        } else {
            $juli = $distance . 'm';
        }
        return $juli;
    }
}

if (!function_exists('authCode')) {
    /**
     * 加密解密函数
     * @param string $string 加密解密字符串
     * @param string $operation ENCODE DECODE
     * @param string $key 别外key
     * @param int $expiry 过期时间
     * @return string
     */
    function authCode($string, $operation = 'DECODE', $key = '', $expiry = 0)
    {

        $ckey_length = 4; // 随机密钥长度 取值 0-32;
        // 加入随机密钥，可以令密文无任何规律，即便是原文和密钥完全相同，加密结果也会每次不同，增大破解难度。
        // 取值越大，密文变动规律越大，密文变化 = 16 的 $ckey_length 次方
        // 当此值为 0 时，则不产生随机密钥

        $key = md5($key ? $key : 'NULL');
        $keya = md5(substr($key, 0, 16));
        $keyb = md5(substr($key, 16, 16));
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';

        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);

        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);

        $result = '';
        $box = range(0, 255);

        $rndkey = array();
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }

        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }

        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }

        if ($operation == 'DECODE') {
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            return $keyc . str_replace('=', '', base64_encode($result));
        }
    }
}

if (!function_exists('randString')) {
    /**
     *  随机数
     *
     * @param string $length 长度
     * @param string $type 类型
     * @return string
     */
    function randString($length = '32', $type = 4)
    {
        $rand = '';
        switch ($type) {
            case '1':
                $randstr = '0123456789';
                break;
            case '2':
                $randstr = 'abcdefghijklmnopqrstuvwxyz';
                break;
            case '3':
                $randstr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
                break;
            default:
                $randstr = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                break;
        }
        $max = strlen($randstr) - 1;
        mt_srand((double)microtime() * 1000000);
        for ($i = 0; $i < $length; $i++) {
            $rand .= $randstr[mt_rand(0, $max)];
        }
        return $rand;
    }
}

if (!function_exists('sensitiveWord')) {
    /**
     * 违禁词检测
     * @param $words
     * @param bool $replace 是否替换违禁词
     * @return array|string
     */
    function sensitiveWord($words, bool $replace = false)
    {
        try {
            //涉政
            $word = RedisTool::get_forever(\constant\RedisConstant::SensitiveWordPolitics, 'config');
            $sensitiveWords = json_decode($word, true);
            if (!$sensitiveWords) {
                $route = __DIR__ . '/../constant/politics.txt';
                $word = file_get_contents($route);
                $sensitiveWords = explode(",", $word);
            }
            $handle = SensitiveHelper::init()->setTree($sensitiveWords);//构建敏感词库树
            $isLegal = $handle->islegal($words);//是否有敏感词
            if ($isLegal) {
                if ($replace) return $handle->replace($words, '***');//敏感词替换成***
                return [false, '时政'];
            }
            //色情
            $word = RedisTool::get_forever(\constant\RedisConstant::SensitiveWordPornographic, 'config');
            $sensitiveWords = json_decode($word, true);
            if (!$sensitiveWords) {
                $route = __DIR__ . '/../constant/pornographic.txt';
                $word = file_get_contents($route);
                $sensitiveWords = explode(",", $word);
            }
            $handle = SensitiveHelper::init()->setTree($sensitiveWords);//构建敏感词库树
            $isLegal = $handle->islegal($words);//是否有敏感词
            if ($isLegal) {
                if ($replace) return $handle->replace($words, '***');//敏感词替换成***
                return [false, '色情'];
            }
            //涉爆
            $word = RedisTool::get_forever(\constant\RedisConstant::SensitiveWordViolence, 'config');
            $sensitiveWords = json_decode($word, true);
            if (!$sensitiveWords) {
                $route = __DIR__ . '/../constant/violence.txt';
                $word = file_get_contents($route);
                $sensitiveWords = explode(",", $word);
            }
            $handle = SensitiveHelper::init()->setTree($sensitiveWords);//构建敏感词库树
            $isLegal = $handle->islegal($words);//是否有敏感词
            if ($isLegal) {
                if ($replace) return $handle->replace($words, '***');//敏感词替换成***
                return [false, '违法犯罪'];
            }
            //广告
            $word = RedisTool::get_forever(\constant\RedisConstant::SensitiveWordAdvertisement, 'config');
            $sensitiveWords = json_decode($word, true);
            if (!$sensitiveWords) {
                $route = __DIR__ . '/../constant/advertisement.txt';
                $word = file_get_contents($route);
                $sensitiveWords = explode(",", $word);
            }
            $handle = SensitiveHelper::init()->setTree($sensitiveWords);//构建敏感词库树
            $isLegal = $handle->islegal($words);//是否有敏感词
            if ($isLegal) {
                if ($replace) return $handle->replace($words, '***');//敏感词替换成***
                return [false, '广告'];
            }
            //骂人
            $word = RedisTool::get_forever(\constant\RedisConstant::SensitiveWordSwearing, 'config');
            $sensitiveWords = json_decode($word, true);
            if (!$sensitiveWords) {
                $route = __DIR__ . '/../constant/swearing.txt';
                $word = file_get_contents($route);
                $sensitiveWords = explode(",", $word);
            }
            $handle = SensitiveHelper::init()->setTree($sensitiveWords);//构建敏感词库树
            $isLegal = $handle->islegal($words);//是否有敏感词
            if ($isLegal) {
                if ($replace) return $handle->replace($words, '***');//敏感词替换成***
                return [false, '脏话'];
            }
            if ($replace) return $words;
            return [true, ''];
        } catch (Exception $e) {
            return [false, $e->getMessage()];
        }
    }
}

if (!function_exists('bubblingSort')) {
    /**
     * 二分排序
     * @param $list
     * @param string $field
     * @param string $sort
     * @return array|mixed
     */
    function bubblingSort($list, $field = 'weight', $sort = 'desc')
    {
        $len = count($list);
        for ($i = 0; $i < $len - 1; $i++) {
            for ($j = 0; $j < $len - $i - 1; $j++) {
                if ($sort == 'desc') {
                    if ($list[$j][$field] < $list[$j + 1][$field]) {
                        $tmp = $list[$j];
                        $list[$j] = $list[$j + 1];
                        $list[$j + 1] = $tmp;
                    }
                } else {
                    if ($list[$j][$field] > $list[$j + 1][$field]) {
                        $tmp = $list[$j];
                        $list[$j] = $list[$j + 1];
                        $list[$j + 1] = $tmp;
                    }
                }
            }
        }
        return $list;
    }
}

if (!function_exists('aesEncrypt')) {
    /**
     *
     * @param string $string 需要加密的字符串
     * @param string $key 密钥
     * @return string
     */
    function aesEncrypt($string, $key = "ONSPEED")
    {
        $data = openssl_encrypt($string, 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
        return strtolower(bin2hex($data));
    }
}

if (!function_exists('aesDecrypt')) {
    /**
     * @param string $string 需要解密的字符串
     * @param string $key 密钥
     * @return string
     */
    function aesDecrypt($string, $key = "ONSPEED")
    {
        try {
            return openssl_decrypt(hex2bin($string), 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
        } catch (\Exception $e) {
            return false;
        }
    }
}

if (!function_exists('checkMobile')) {
    /**
     * 检查手机号
     * @param $mobile
     * @return bool
     */
    function checkMobile($mobile)
    {
        $isMob = "/^1[3456789]\d{9}/";
        $isTel2 = "/^([0-9]{3,4}-)?[0-9]{7,8}$/";
        $res = preg_match($isMob, $mobile) || preg_match($isTel2, $mobile);
        return (bool)$res;
    }
}

if (!function_exists('getRedisData')) {
    /**
     * @param $mode int 派发模式
     * @param $key string key
     * @return array|void
     */
    function getRedisData($mode, $key)
    {
        $userId = 0;
        $lockValue = uniqid();
        while (true) {
            $exist = RedisTool::get_exists($key, 'list');
            if (!$exist) return [0, []];
            $lockKey = $key . '_lock';
            if (RedisTool::get_exists($lockKey, 'list')) {
                if ($lockValue != RedisTool::get_time($lockKey, 'list')) {
                    usleep(5000);
                    continue;
                }
            } else RedisTool::setLock($lockKey, rand(0, 99999), 5, 'list');
            if (in_array($mode, [1, 2, 8])) {
                $info = RedisTool::get_lPop($key, 'list');
                if ($info['in_assign']) {
                    RedisTool::del($lockKey, 'list');
                    return [1, $info];
                }
                $userId = $userId ?: $info['user_id'];
                //执行一圈若还无人则返回
                if ($userId == $info['user_id']) {
                    RedisTool::del($lockKey, 'list');
                    return [0, []];
                }
            } elseif ($mode == 3) {
                $info = RedisTool::get_zSet_desc($key, 0, 1, 'list')[0];
                RedisTool::del($lockKey, 'list');
                if ($info['in_assign']) return [1, $info];
                return [0, []];
            } else {
                $info = RedisTool::get_zSet_asc($key, 0, 1, 'list')[0];
                RedisTool::del($lockKey, 'list');
                if ($info['in_assign']) return [1, $info];
                return [0, []];
            }
        }
    }
}

if (!function_exists('getFirstUserId')) {
    /**
     * 获取第一个派发ID
     * @return int
     */
    function getFirstUserId($mode, $key, $userArr)
    {
        $times = 0;
        while ($times <= 4) {
            $times++;
            $type = RedisTool::type($key, 'list');
            if (in_array($mode, [1, 2, 8]) && $type == 3) { //设置为队列，存储为队列
                list($code, $data) = getRedisData($mode, $key);
            } elseif (in_array($mode, [1, 2, 8]) && $type == 4) { //设置为队列，存储为集合
                list($code, $data) = getRedisData($type, $key);
            } elseif (in_array($mode, [3, 4]) && $type == 4) { //设置为集合，存储为集合
                list($code, $data) = getRedisData($mode, $key);
            } else {//设置为集合，存储为队列
                list($code, $data) = getRedisData(1, $key);
            }
            if (!$code) return 0;
            if (in_array($data['user_id'], $userArr))
                return $data['user_id'];
        }
        return 0;
    }
}